<script setup lang="ts">
import Konva from 'konva';
import type {KonvaCircle, KonvaImage} from "~/utils/konvaUtils";

const freeDraw = ref(false)
type DrawMode = 'brush' | "eraser" | "line"
//编辑模式，变换、裁剪
type EditMode = 'transform' | 'clip'
const brushMode = ref<DrawMode>('line')
const editMode = ref<EditMode>('clip')
const configImage = ref<KonvaImage[]>([])
const configCircles = ref<KonvaCircle[]>([])
const stage = ref()

const configKonva = ref({
  width: 800,
  height: 1200,
  layers: [
    {
      name: 'layer1',
      draggable: false,
      groups: [
        {
          name: 'image_group',
          draggable: false,
          images: configImage.value,
          circles:[]
        }
      ]
    },
    {
      name: 'layer2',
      draggable: false,
      groups: [
        {
          name: 'shape_group',
          draggable: false,
          images:[],
          circles: configCircles.value
        }
      ]
    },
    {
      name: 'layer3',
      draggable: false,
      groups: [
        {
          name: 'clip_group',
          draggable: false,
          images: [],
          circles:[]
        }
      ]
    }
  ]
})

onMounted(() => {
  const url = 'https://wangbo0808.oss-cn-shanghai.aliyuncs.com/aidraw/00001.png';
  handleLoadImage(url)
})

const configLine = ref({
  points: [0, 0, 100, 200, 300, 300],
  tension: 0,
  closed: true,
  stroke: 'white',
  fill: 'black',
  strokeWidth: 10
})

configCircles.value.push(
    {
      name: 'circle1',
      x: 100,
      y: 100,
      radius: 70,
      fill: "red",
      stroke: "black",
      strokeWidth: 4,
      draggable: true
    }
)
configCircles.value.push(
    {
      name: 'circle2',
      x: 300,
      y: 300,
      radius: 70,
      fill: "red",
      stroke: "black",
      strokeWidth: 3,
      draggable: true
    }
)


const handleLoadImage = (url: string) => {
  const imageObj = new Image();
  imageObj.src = url
  imageObj.onload = () => {
    console.log('imageObj onload')
    imageObj.crossOrigin = 'Anonymous';
    const image = {
      name: 'image1',
      x: 0,
      y: 0,
      image: imageObj,
      scaleX: 0.5,
      scaleY: 0.5,
      draggable: true,
    } as KonvaImage
    const imageNode = configImage.value.find(item => item.name === image.name)
    if (!imageNode) {
      configImage.value.push(image)
    }
    console.log(configImage.value)
  }
}


const changePosition = () => {
  // configCircle.value.x += 10
}
const download = () => {
  const data = layer.value.getStage().toDataURL()
  console.log(data)
  downloadURI(data, 'stage.png');
}
const downloadURI = (uri, name) => {
  const link = document.createElement('a');
  link.download = name;
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

const brush = ref({
  name: 'brush1',
  x: 0,
  y: 0,
  radius: 40,
  fill: "black",
} as KonvaCircle)

// 变换
const transformer = ref()
const selectedShapeName = ref('')
const handleStageMouseDown = (e) => {
  // clicked on stage - clear selection
  console.log('点击事件', e.target)
  if (freeDraw.value) {
    if (brushMode.value === 'brush') {

      //画一个圆
      const pos = stage.value.getStage().getPointerPosition()
      brush.value.x = pos.x
      brush.value.y = pos.y
      brush.value.globalCompositeOperation = brushMode.value === 'brush' ? 'source-over' : 'destination-out'
      const circle = new Konva.Circle(brush.value);
      const layer3=stage.value.getStage()
      console.log('layer3',layer3)
      // layer2.value.getStage().add(circle);
    }
    if (brushMode.value === 'line') {
      //画一条线
      const pos = stage.value.getStage().getPointerPosition()
      configLine.value.points = [pos.x, pos.y, pos.x, pos.y]
      // layer2.value.getStage().add(new Konva.Line(configLine.value))
    }
    stage.value.getStage().on('mousemove', handleStageMouseMove)
    // layer.value.draw();
  } else {
    //裁剪模式
    if (editMode.value === 'clip') {
      //判断clipGroup是否存在，如果不存在创建一个clipGroup
      const clip_layer=stage.value.getStage().children[2]
      const clipGroup = clip_layer.children[0]
      console.log(clipGroup)
      //将裁剪对象的dragable设置为false
      let image = clip_layer.getStage().findOne('.image1')
      console.log('image', image)
      if (!image) {
        image = new Konva.Image(configImage.value[0])
      }
      image.draggable(false)
      //将裁剪的对象添加到clipGroup
      clipGroup.add(image)
      clip_layer.getStage().add(clipGroup)
      //点击的是裁剪框或者裁剪框的操作节点，不采取任何动作
      if (e.target.getParent().className === 'Transformer' || e.target.attrs.name === 'clip_rect') {
        return;
      }
      //画一个矩形
      //判断是否已经存在一个矩形
      const rect = clip_layer.getStage().findOne('.clip_rect')
      if (rect) {
        rect.destroy()
      }
      const pos = stage.value.getStage().getPointerPosition()
      console.log(pos)
      const rect_new = new Konva.Rect({
        name: 'clip_rect',
        x: pos.x,
        y: pos.y,
        width: 0,
        height: 0,
        fill: 'black',
        opacity: 0.5,
        strokeWidth: 5,
        draggable: true
      })
      clipGroup.add(rect_new)
      selectedShapeName.value = 'clip_rect'

      stage.value.getStage().on('mousemove', handleStageMouseMove)
      updateTransformer();
      return;
      // layer.value.getStage().draw();
    }
    if (e.target === e.target.getStage()) {
      selectedShapeName.value = '';
      // updateTransformer();
      return;
    }
    // clicked on transformer - do nothing
    const clickedOnTransformer =
        e.target.getParent().className === 'Transformer';
    if (clickedOnTransformer) {
      return;
    }
    // find clicked rect by its name
    const name = e.target.name();
    const node = configImage.value.find((r) => r.name === name);
    console.log(node)
    if (node) {
      selectedShapeName.value = name;
    } else {
      selectedShapeName.value = '';
    }
    updateTransformer();
  }
}
const handleTransformEnd = (e) => {
  // shape is transformed, let us save new attrs back to the node
  // find element in our state
  const node = configImage.value.find(
      (r) => r.name === selectedShapeName.value
  );
  // update the state
  if (node) {
    node.x = e.target.x();
    node.y = e.target.y();
    node.rotation = e.target.rotation();
    node.scaleX = e.target.scaleX();
    node.scaleY = e.target.scaleY();
    // change fill
    // rect.fill = Konva.Util.getRandomColor();
  }
  if (editMode.value === 'clip') {
    //裁剪模式

  }

}
const updateTransformer = () => {
  // here we need to manually attach or detach Transformer node
  const transformerNode = transformer.value.getNode();

  const stage = transformerNode.getStage();

  // selectedShapeName.value = transformerNode.node()?.name() || '';//??
  console.log(stage)
  const selectedNode = stage.findOne('.' + selectedShapeName.value);
  console.log(selectedShapeName.value, selectedNode)
  // do nothing if selected node is already attached
  if (selectedNode === transformerNode.node()) {
    return;
  }

  if (selectedNode) {
    // attach to another node
    transformerNode.nodes([selectedNode]);
  } else {
    // remove transformer
    transformerNode.nodes([]);
  }
}

const handleStageMouseMove = (e) => {
  console.log('event', e)
  if (freeDraw.value) {
    if (brushMode.value === 'brush') {
      console.log(e)
      // prevent scrolling on touch devices
      e.evt.preventDefault();
      const pos = stage.value.getStage().getPointerPosition();
      brush.value.x = pos.x
      brush.value.y = pos.y
      brush.value.globalCompositeOperation = brushMode.value === 'brush' ? 'source-over' : 'destination-out'
      configKonva.value.layers[1].groups[0].circles.push(brush.value)
      // const circle = new Konva.Circle(brush.value);
      // layer2.value.getStage().add(circle);
    }
    if (brushMode.value === 'line') {
      const pos = stage.value.getStage().getPointerPosition()
      console.log(pos)
      configLine.value.points = [...configLine.value.points, pos.x, pos.y]
    }
  } else {
    if (editMode.value === 'clip') {
      const rect = layer.value.getStage().findOne('.clip_rect')
      if (rect) {
        const pos = stage.value.getStage().getPointerPosition()
        rect.width(pos.x - rect.x())
        rect.height(pos.y - rect.y())
        // layer.value.getStage().draw();
      }
    }
  }
}
const handleStageMouseUp = () => {
  if (freeDraw.value) {
    if (brushMode.value === 'line') {
    } else {
      stage.value.getStage().off('mousemove', handleStageMouseMove)
    }
  } else {
    if (editMode.value === 'clip') {
      stage.value.getStage().off('mousemove', handleStageMouseMove)
    }
  }

}

//确认裁剪
const handleConfirmClip = () => {
  const rect = layer.value.getStage().findOne('.clip_rect')
  // console.log(rect)
  if (rect) {
    //裁剪
    const image = layer.value.getStage().findOne('.image1')
    console.log(image)
    if (image) {
      Object.assign(configKonva.value.layers[0].groups[0], {
        clip: {
          x: rect.x(),
          y: rect.y(),
          width: rect.width(),
          height: rect.height()
        }
      })
    }
    //重新绘制
    layer.value.getStage().draw();

    //删除矩形
    rect.destroy()
    selectedShapeName.value = ''
    //结束裁剪模式
    // editMode.value = 'transform'
    // 恢复dragable
    if (image) {
      // image.draggable(true)
    }
  }
}


</script>

<template>
  <v-sheet>
    <v-stage ref="stage" :config="configKonva" @mousedown="handleStageMouseDown" @mouseup="handleStageMouseUp"
             @touchstart="handleStageMouseDown">
      <v-layer v-for="(layer,index) in configKonva.layers" :key="index">
        <v-group v-for="(group,index) in layer.groups" :key="index">
          <v-image v-for="(image,index) in group.images" :key="index" :config="image"></v-image>
        </v-group>
      </v-layer>
      <v-layer>
        <v-circle v-for="(item,index) in configCircles" :key="index" :config="item"
                  @transformend="handleTransformEnd"></v-circle>
        <v-line :config="configLine"></v-line>
        <v-transformer ref="transformer"/>
      </v-layer>
    </v-stage>
  </v-sheet>
  <v-btn @click="changePosition">改变位置</v-btn>
  <v-btn @click="download">下载图层</v-btn>
  <v-btn @click="freeDraw=!freeDraw">{{ freeDraw ? '画布模式' : '自由模式' }}</v-btn>
  <v-btn @click="brushMode='brush'">画刷</v-btn>
  <v-btn @click="brushMode='line'">线</v-btn>
  <v-btn @click="brushMode='eraser'">橡皮</v-btn>

  <!--  确认裁剪-->
  <v-btn @click="handleConfirmClip">裁剪</v-btn>
  <v-btn @click="editMode='transform'">变换</v-btn>
</template>

<style scoped lang="scss">
.grid-background-lg {
  background: linear-gradient(
          45deg,
          rgba(0, 0, 0, 0.1) 25%,
          transparent 25%,
          transparent 75%,
          rgba(0, 0, 0, 0.1) 75%,
          rgba(0, 0, 0, 0.1) 100%
  ),
  linear-gradient(
          45deg,
          rgba(0, 0, 0, 0.1) 25%,
          transparent 25%,
          transparent 75%,
          rgba(0, 0, 0, 0.1) 75%,
          rgba(0, 0, 0, 0.1) 100%
  );
  /* 背景大小必须小于盒子的大小 */
  background-size: 40px 40px;
  /* 第二种渐变的偏移必须为为背景大小的一半 */
  background-position: 0 0, 20px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;

}

.grid-background-sm {
  background: linear-gradient(
          45deg,
          rgba(0, 0, 0, 0.1) 25%,
          transparent 25%,
          transparent 75%,
          rgba(0, 0, 0, 0.1) 75%,
          rgba(0, 0, 0, 0.1) 100%
  ),
  linear-gradient(
          45deg,
          rgba(0, 0, 0, 0.1) 25%,
          transparent 25%,
          transparent 75%,
          rgba(0, 0, 0, 0.1) 75%,
          rgba(0, 0, 0, 0.1) 100%
  );
  /* 背景大小必须小于盒子的大小 */
  background-size: 20px 20px;
  /* 第二种渐变的偏移必须为为背景大小的一半 */
  background-position: 0 0, 10px 10px;
  width: 100%;
  height: 100%;

}
</style>